package com.dream.dreamhouse.common.utils;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.dream.dreamhouse.common.entity.IpLocation;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author lizhen
 * @date 2025/6/16 11:43
 */
@Slf4j
//@UtilityClass
public class IpUtils {

    /**
     * 字符常量0
     */
    private static final String ZERO = "0";
    /**
     * 本级ip
     */
    private static final String LOCALHOST = "127.0.0.1";

    // 模拟企业内部IP分配表（实际应从数据库或配置文件加载）
    private static final Map<String, String> IP_REGION_MAP = new HashMap<>();

    static {
        // 示例：IP段与部门/区域的映射关系
        IP_REGION_MAP.put("192.168.1.0/24", "湖北省");
        // ... 更多配置
    }

    /**
     * 获取客户端的IP地址
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ipAddress = request.getHeader("X-Forwarded-For");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (LOCALHOST.equals(ipAddress)) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                    ipAddress = inet.getHostAddress();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
            }
        }
        // 对于通过多个代理转发的情况，取第一个非unknown的IP地址。
        // 这里假设第一个IP为真实IP，后面的为代理IP。
        if (ipAddress != null && ipAddress.length() > 15) {
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

    /**
     * 根据iP获取归属地信息
     *
     * @return
     */
    public static IpLocation getLocation(String ip) {
        IpLocation location = new IpLocation();
        location.setIp(ip);
        try (InputStream inputStream = IpUtils.class.getResourceAsStream("/ip2region.xdb");) {
            byte[] bytes = IoUtil.readBytes(inputStream);
            Searcher searcher = Searcher.newWithBuffer(bytes);
            String region = searcher.search(ip);
            if (StrUtil.isAllNotBlank(region)) {
                // xdb返回格式 国家|区域|省份|城市|ISP，
                // 只有中国的数据绝大部分精确到了城市，其他国家部分数据只能定位到国家，后前的选项全部是0
                String[] result = region.split("\\|");
                location.setCountry(ZERO.equals(result[0]) ? StrUtil.EMPTY : result[0]);
                location.setProvince(ZERO.equals(result[2]) ? StrUtil.EMPTY : result[2]);
                location.setCity(ZERO.equals(result[3]) ? StrUtil.EMPTY : result[3]);
                location.setIsp(ZERO.equals(result[4]) ? StrUtil.EMPTY : result[4]);
            }
            searcher.close();
        } catch (Exception e) {
            log.error("ip地址解析异常,error:{}", e);
            return location;
        }
        return location;
    }

    /**
     * 解析内网IP对应的区域信息
     *
     * @param ip 客户端IP地址
     * @return 区域描述（如部门、机房），未匹配返回null
     */
    public static String parseIntranetRegion(String ip) {
        if (isIntranetIP(ip)) {
            // 遍历IP段匹配（实际建议使用更高效的IP段匹配算法）
            for (Map.Entry<String, String> entry : IP_REGION_MAP.entrySet()) {
                String cidr = entry.getKey();
                return entry.getValue();
            }
        }
        return null;
    }

    /**
     * 判断是否为内网IP
     */
    public static boolean isIntranetIP(String ip) {
        // 简化实现，实际建议使用正则表达式或IP地址库判断
        String[] parts = ip.split("\\.");
        if (parts.length != 4) return false;

        int first = Integer.parseInt(parts[0]);
        int second = Integer.parseInt(parts[1]);

        // 匹配10.0.0.0/8
        if (first == 10) return true;
        // 匹配172.16.0.0/12
        if (first == 172 && second >= 16 && second <= 31) return true;
        // 匹配192.168.0.0/16
        if (first == 192 && second == 168) return true;

        return false;
    }

    /**
     * 判断IP是否匹配CIDR网段
     */
    private static boolean ipMatchesCIDR(String ip, String cidr) {
        // 实际项目中建议使用成熟的CIDR匹配库（如Apache Commons Net）
        // 简化示例省略具体实现...
        return false;
    }
}

